<?php

defined('BASEPATH') or die('forbidden');

/**
 * 缓存类(使用文件式缓存或apc cache)
 * @author  Karson
 * @name    cache.php
 * @since   2013-7-11 15:36:02
 */
class Cache {

    var $dir;    //缓存目录
    var $time;   //缓存时间
    var $config;  //缓存后缀
    var $suffix;  //缓存后缀
    var $separate; //缓存分隔符
    var $header;  //缓存头部代码
    var $type;
    var $publiccache = array();   //公共缓存数组

    function Cache() {
        $framework = &get_instance('controller');
        $this->config = &$framework->config;
        if (isset($this->config['apc']) && $this->config['apc']['state'] && extension_loaded('apc') && ini_get('apc.enabled')) {
            //APC缓存
            $type = 'apc';
            //公共缓存
            $this->publiccache = array(
                'configvalue',
                'formula',
                'vipdata',
                'activitysample',
                'bosssample',
                'buffconfig',
                'combinerecipesample',
                'drugsample',
                'drugheartsample',
                'drugsoulsample',
                'equipsample',
                'escortcar',
                'gangsoulsample',
                'gemsample',
                'gembuffsample',
                'growvalue',
                'herosample',
                'itemconfig',
                'industrysample',
                'mopupconfig',
                'pointconfig',
                'rewardconfig',
                'roulettesample',
                'signinconfig',
                'skillconfig',
                'slavelogpost',
                'soulsample',
                'stageconfig',
                'suitcompose',
                'suitpropery',
                'suppresspoint',
                'suppressstage',
                'taskconfig',
                'tattoosample',
                'trusteeshipconfig',
            );
        } else {
            //文件缓存
            $type = 'file';
            $this->dir = CACHE_DIR;
            $this->time = CACHE_TIME;
            $this->separate = CACHE_SEPARATE;
            $this->suffix = CACHE_SUFFIX;
            $this->header = CACHE_HEADER;
            if (!is_dir($this->dir) && !mkdir($this->dir)) {
                throw new Exception("缓存目录创建失败！");
            }
        }
        $this->type = $type;
    }

    /**
     * 设置缓存值
     * @param string $name 缓存名称
     * @param mixed $data 缓存数据，可以是字符，数组，对象等数据
     * @param int $time 缓存时间，默认0，为0时永久缓存
     * @param boolean $public 是否公用缓存
     * @return bool 成功返回true,失败返回false
     */
    function set($name, $data, $time = 0, $public = false) {
        if ($name != '' && $data != '') {
            if ($this->type == 'apc') {
                $public = $public || in_array($name, $this->publiccache) ? TRUE : FALSE;
                return apc_store(($public ? '' : $this->config['area_id']) . $name, $data, $time);
            } else {
                $name = $this->get_cache_name($name);
                $name = $this->get_cache_file($name);
                @file_put_contents($name, $this->header . $time . $this->separate . json_encode($data), LOCK_EX);
                @chmod($name, 0777);
                @touch($name, time() + $time);
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取缓存值
     * @param string $name 缓存名称
     * @param boolean $public 是否公用缓存
     * @return mixed 成功返回缓存数据，失败返回false
     */
    function get($name, $public = false) {
        if ($name == '')
            return false;
        if ($this->type == 'apc') {
            $public = $public || in_array($name, $this->publiccache) ? TRUE : FALSE;
            return apc_fetch(($public ? '' : $this->config['area_id']) . $name);
        } else {
            $name = $this->get_cache_name($name);
            $name = $this->get_cache_file($name);
            if (file_exists($name)) {
                $content = file_get_contents($name);
                $content = str_replace($this->header, '', $content);
                $data = explode($this->separate, $content);
                $data[0] = intval($data[0]);
                return (isset($data[1]) && ($data[0] === 0 || (time() - filemtime($name)) < $data[0])) ? json_decode($data[1], true) : false;
            } else {
                return false;
            }
        }
    }

    /**
     * 清除缓存
     * @param string $name 缓存名称，默认为空，为空时清空所有缓存
     */
    function clear($name = '', $public = false) {
        if ($this->type == 'apc') {
            $public = $public || in_array($name, $this->publiccache) ? TRUE : FALSE;
            if ($name == '') {
                //清空用户缓存
                apc_clear_cache("user");
                //清除opcode缓存
                apc_clear_cache('opcode');
            } else {
                apc_delete(($public ? '' : $this->config['area_id']) . $name);
            }
        } else {
            if ($name == '') {
                $files = scandir($this->dir);
                foreach ($files as $file) {
                    if ($file == '.' || $file == '..')
                        continue;
                    @unlink($this->dir . '/' . $file);
                }
            } else {
                $name = $this->get_cache_name($name);
                @unlink($this->get_cache_file($name));
            }
        }
    }

    /**
     * 获取缓存名
     * @param string $name
     */
    function get_cache_name($name) {
        return "cache_" . md5($name);
    }

    /**
     * 获取缓存文件路径
     * @param string $name
     */
    function get_cache_file($name) {
        return $this->dir . '/' . $name . $this->suffix;
    }

}